// 利用分离轴定理与最小偏移向量

// 形状
function Shape(){
	this.x = undefined;
	this.y = undefined;
	this.strokeStyle = 'rgba(255, 253, 208, 0.9)';
	this.fillStyle = 'rgba(147, 197, 114, 0.8)';
}

Shape.prototype = {
	// 碰撞函数
	collidesWith: function(otherShape){
		var axes = this.getAxes().concat(otherShape.getAxes()); // 轴线

		return !this.separationOnAxes(axes, otherShape);
	},

	// 最小平移向量
	minimumTransformVector: function(axes, shape){
		var minimumOverlap = 10000,
			overlap,
			axisWithSmallestOverlap;

		for(var i = 0; i < axes.length; i++){
			var axis = axes[i],
				projection1 = shape.project(axis);
				projection2 = this.project(axis);

			overlap = projection1.overlap(projection2);

			if(!overlap){
				return {
					axis: undefined, // 没有碰撞
					overlap: 0
				};
			}else{
				if(overlap < minimumOverlap){
					minimumOverlap = overlap;
					axisWithSmallestOverlap = axis;
				}
			}
		}

		return {
			axis: axisWithSmallestOverlap, // 受测图形重叠部分长度最小的轴
			overlap: minimumOverlap // 受测图形重叠部分最小长度
		};
	},

	// 分离轴
	separationOnAxes: function(axes, otherShape){
		for(var i = 0; i < axes.length; i++){
			var axis = axes[i],
				projection1 = otherShape.project(axis);
				projection2 = this.project(axis);
			
			if(!projection1.overlaps(projection2)){
				return true; // 尽早退出，没有必要测试剩余的轴
			}
		}

		return false;
	},

	// 获取分离轴
	getAxes: function(){
		throw 'getAxes() not implemented.'; // 抛出异常，该方法尚未实现
	},

	// 投影
	project: function(axis){
		throw 'project(axis) not implemented.';
	},

	// 移动
	move: function(dx, dy){
		throw 'move(dx, dy) not implemented.'
	},

// 绘制方法.......................................................................
	// 创建路径
	createPath: function(context){
		throw 'createPath(context) not implemented.'
	},

	// 填充
	fill: function(context){
		context.save();
		context.fillStyle = this.fillStyle;
		this.createPath(context);
		context.fill();
		context.restore();
	},

	// 描边
	stroke: function(context){
		context.save();
		context.strokeStyle = this.strokeStyle;
		this.createPath(context);
		context.stroke();
		context.restore();
	},

	// 判断当前点是否在路径中
	isPointInPath: function(context, x, y){
		this.createPath(context);
		return context.isPointInPath(x, y);
	}

};